home *** CD-ROM | disk | FTP | other *** search
- ;* DSMMIX.ASM
- ;*
- ;* Digital Sound Mixer low-level mixing routines
- ;*
- ;* $Id: dsmmix.asm,v 1.9 1997/01/16 18:41:59 pekangas Exp $
- ;*
- ;* Copyright 1996,1997 Housemarque Inc.
- ;*
- ;* This file is part of the MIDAS Sound System, and may only be
- ;* used, modified and distributed under the terms of the MIDAS
- ;* Sound System license, LICENSE.TXT. By continuing to use,
- ;* modify or distribute this file you indicate that you have
- ;* read the license and understand and accept it fully.
- ;*
-
- IDEAL
- P386
-
- ; Possibly environment dependent code is marked with *!!*
-
-
- INCLUDE "lang.inc"
- INCLUDE "errors.inc"
- INCLUDE "sdevice.inc"
- INCLUDE "dsm.inc"
- INCLUDE "mglobals.inc"
-
- IFNDEF NOEMS
- INCLUDE "ems.inc"
- ENDIF
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Macro: NumLabel lblname, lblnum
- ;*
- ;* Description: Creates a numbered label in the source, format _namenum
- ;* (eg. _table1)
- ;*
- ;* Input: lblname name for the label
- ;* lblnum number for the label
- ;*
- ;\***************************************************************************/
-
- MACRO NumLabel lblname, lblnum
- _&lblname&lblnum:
- ENDM
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Macro: JmpTable lblname, lblcount
- ;*
- ;* Description: Creates a jump offset table in the source. The table consists
- ;* of near offsets of labels _lblname0 - _lblnameX
- ;*
- ;* Input: lblname name of labels to be used for the table
- ;* lblcount number of labels
- ;*
- ;\***************************************************************************/
-
- MACRO defoffs lblname, lblnum
- IFDEF __16__
- DW offset _&lblname&lblnum
- ELSE
- DD offset _&lblname&lblnum
- ENDIF
- ENDM
-
- MACRO JmpTable lblname, lblcount
- numb = 0
- REPT lblcount
- defoffs lblname, %numb
- numb = numb + 1
- ENDM
- ENDM
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Macro: MixLoop mname, mixLp, DIinc, counter
- ;*
- ;* Description: Generates code for inner mixing loop, REPeaTed 16 times.
- ;* Mixing is started with a near call to some label in the
- ;* mixing loop and ends with a near return
- ;*
- ;* Input: mname mixing loop name (ie. m8mna)
- ;* mixLp macro that contains code for mixing loop
- ;* DIinc _di increment after each loop (16 times)
- ;* counter loop counter (ie. cx)
- ;*
- ;\***************************************************************************/
-
- MACRO MixLoop mname, mixLp, DIinc, counter
- LOCAL lp
-
- LABEL &mname _int
- JmpTable &mname, 17
-
- lp:
- num = 0
- REPT 16
- NumLabel &mname, %num
- &mixLp %num
- num = num + 1
- ENDM
- NumLabel &mname, %num
-
- IF DIinc NE 0
- add di,DIinc ; mix next DIInc bytes
- ENDIF
- dec counter
- jnz lp
- retn
-
- ENDM MixLoop
-
-
-
-
-
- DATASEG
-
- ; Mixing routine temporary variables: (in data segment for easier access and
- ; speed)
-
- D_int lim1 ;FIXME
- D_int lim2
-
- D_ptr sample ; pointer to beginning of sample data
- D_ptr chan ; pointer to current channel struct
- D_int lpStart ; current loop start
- D_int lpEnd ; current loop end
- D_int lpType ; current loop type
- D_int direction ; current playing direction
- D_int released ; sound released flag - 1 if sound has been
- ; released but first loop is still being
- ; played
- D_int ALEChange ; 1 if Amiga Loop Emulation sample change
- ; is necessary when sample or loop ends
- D_int mixLeft ; number of elements left to mix
- D_ptr dest ; mixing destination pointer
- D_long incr ; sample playing position increment
- D_long maxMix ; maximum number of sample bytes that may be
- ; mixed during this mixing process
- D_int position ; sample playing position whole part
- D_int posLow ; sample playing position fractional part
- ; (only lower 16 bits are used)
- D_ptr mixRout ; pointer to mixing routine
- IFDEF __16__
- D_int prevPos ; position before mixing (required for
- ; checking for bidirectional loop start in
- ; 16-bit modes under some circumstances)
- ENDIF
- D_int mixLoop ; pointer to mixing loop start
-
- IFDEF __16__
- D_int mixCount ; mixing counter for 16-bit mixing loops
- ENDIF
-
- D_int panning ; current channel panning position
- D_int fracIncr ; mixing position fraction increment in some
- ; mixing routines
- D_int chanNum ; channel number
- D_ptr loopCallback ; loop callback function
-
- leftVolume DB ? ; left channel volume in smooth panning
- rightVolume DB ? ; right channel volume in smooth panning
-
-
-
- CODESEG
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int dsmMix(unsigned channel, void *mixRoutine,
- ;* unsigned volume, unsigned numElems);
- ;*
- ;* Description: Mixes data for one channel. Used internally by dsmMixData().
- ;*
- ;* Input: unsigned channel channel number
- ;* void *mixRoutine pointer to low-level mixing routine
- ;* unsigned volume actual playing volume (volume in
- ;* channel structure is ignored)
- ;* unsigned numElems number of elements to mix (see
- ;* dsmMixData())
- ;*
- ;* Returns: MIDAS error code
- ;*
- ;\***************************************************************************/
-
- PROC dsmMix _funct channel : _int, mixRoutine : _ptr, \
- volume : _int, numElems : _int
- USES _si,_di,_bx
-
- cld
-
- mov ax,ds
- IFDEF __32__
- mov es,ax
- ENDIF
- IFDEF __16__
- mov fs,ax ; fs will be used to access variables
- ENDIF ; in data segment when ds is destroyed
-
- mov _ax,[numElems] ; mixLeft = number of elements left
- mov [mixLeft],_ax ; to mix
-
- mov _ax,[channel] ; make sure we have channel number
- mov [chanNum],_ax ; always accessable
-
- ; Set dest to current mixing position in buffer:
- COPYPTR [dest],[dsmMixBuffer]
-
- ; Point mixRout to mixing routine:
- COPYPTR [mixRout],[mixRoutine]
-
- ; Point _gsbx and chan to current channel structure:
- LOADPTR gs,_bx,[dsmChannels]
- imul _ax,[channel],SIZE dsmChannel
- add _bx,_ax
- mov [_int chan],_bx
- IFDEF __16__
- ;*!!*
- mov [word chan+2],gs
- ENDIF
-
- ; Copy loop callback pointer:
- mov eax,[_gsbx+dsmChannel.loopCallback]
- mov [loopCallback],eax
-
- ; Check that there is a sample:
- cmp [_gsbx+dsmChannel.sampleType],smpNone
- je @@nodata
-
- ; Store current playing direction in direction:
- mov _ax,[_gsbx+dsmChannel.direction]
- mov [direction],_ax
-
- ; Copy position whole and fractional parts to internal variables:
- mov _ax,[_gsbx+dsmChannel.playPos]
- mov [position],_ax
- mov _ax,[_gsbx+dsmChannel.playPosLow]
- mov [posLow],_ax
-
- ; Copy channel panning position
- mov _ax,[_gsbx+dsmChannel.panning]
- mov [panning],_ax
-
- ; Calculate sample position increment for each destination element:
- mov eax,[_gsbx+dsmChannel.rate] ; playing rate
- mov edx,eax ; eax = sample pos increment =
- shl eax,16 ; rate / dsmMixRate
- shr edx,16
- IFDEF __16__
- xor ecx,ecx
- ENDIF
- mov _cx,[dsmMixRate] ; (16.16 bit fixed point number)
- div ecx
- mov [incr],eax ; store position increment
-
- ; Calculate maximum number of sample bytes that can be mixed during
- ; the whole mixing process for this channel (used to prevent divide
- ; overflows and speed up some processing):
- IFDEF __16__
- xor eax,eax
- ENDIF
- mov _ax,[numElems] ; eax = number of elements
- mul [incr] ; multiply with position increment
- shrd eax,edx,16 ; convert to integer
- add eax,2 ; add two for safety and rounding
- mov [maxMix],eax ; margin
-
-
- @@newsample: ; ALE logic jumps here if sample is changed
-
- ; Check channel status:
- mov _ax,[_gsbx+dsmChannel.status]
- cmp _ax,dsmChanStopped ; channel stopped?
- je @@nodata ; if yes, there is no data to mix
- cmp _ax,dsmChanEnd ; channel ended?
- je @@nodata ; if yes, there is no data to mix
- cmp _ax,dsmChanPlaying ; playing normally?
- je @@playnorm ; if yes, use first loop
-
- ; Channel sound has been released. Check if the first loop is still
- ; being played, and if so, mark playing released so that the loop will
- ; be changed when the end of the first loop is reached. Otherwise
- ; just use the second loop:
- cmp [_gsbx+dsmChannel.loopNum],2
- je @@loop2
- mov [released],1 ; change loop when loop end is reached
- jmp @@loop1 ; use first loop
-
- @@loop2:
- ; Use second loop:
- mov _ax,[_gsbx+dsmChannel.loop2Start]
- mov [lpStart],_ax
- mov _ax,[_gsbx+dsmChannel.loop2End]
- mov [lpEnd],_ax
- mov _ax,[_gsbx+dsmChannel.loop2Type]
- mov [lpType],_ax
- jmp @@loopok1
-
-
- @@playnorm:
- mov [released],0 ; playing not released
-
- @@loop1:
- ; Use first loop:
- mov _ax,[_gsbx+dsmChannel.loop1Start]
- mov [lpStart],_ax
- mov _ax,[_gsbx+dsmChannel.loop1End]
- mov [lpEnd],_ax
- mov _ax,[_gsbx+dsmChannel.loop1Type]
- mov [lpType],_ax
-
- @@loopok1:
- ; Check if sample has been changed so that ALE sample changing logic
- ; may have to be used later (sample has been changed and both current
- ; and new samples have Amiga compatible looping):
- cmp [_gsbx+dsmChannel.sampleChanged],0
- je @@noalech
- cmp [_gsbx+dsmChannel.loopMode],sdLoopAmiga
- je @@1
- cmp [_gsbx+dsmChannel.loopMode],sdLoopAmigaNone
- jne @@noalech
-
- @@1:
- ; Point _essi to new sample:
- LOADPTR es,_si,[dsmSamples]
- imul _ax,[_gsbx+dsmChannel.sampleHandle],SIZE dsmSample
- add _si,_ax
- cmp [_essi+dsmSample.loopMode],sdLoopAmigaNone
- je @@alech
- cmp [_essi+dsmSample.loopMode],sdLoopAmiga
- jne @@noalech
-
- @@alech:
- ; Sample has been changed and both current and new sample have Amiga
- ; compatible looping - Amiga Loop Emulation sample change will occur
- ; if current sample ends or reaches loop end:
- mov [ALEChange],1
- jmp @@aleok1
-
- @@noalech:
- ; Sample will not be changed:
- mov [ALEChange],0
-
- @@aleok1:
- ; Get sample start address:
- mov edx,[ebx+dsmChannel.sample]
-
- ; We'll need to divide the sample start address by sample size to
- ; make sample start address and mixing position match:
- mov _ax,[_gsbx+dsmChannel.sampleType]
- cmp _ax,smp8bitStereo
- je @@smp8bitStereo
- cmp _ax,smp16bitMono
- je @@smp16bitMono
- cmp _ax,smp16bitStereo
- je @@smp16bitStereo
- jmp @@sampleok
-
- @@smp8bitStereo:
- @@smp16bitMono:
- shr edx,1
- jmp @@sampleok
-
- @@smp16bitStereo:
- shr edx,2
-
- @@sampleok:
- mov [sample],edx
- ; Loop sample:
- @@loop:
- cmp [mixLeft],0 ; better safe than sorry
- je @@alldone
-
- ; Check if we are really playing a stream:
- cmp [_gsbx+dsmChannel.sampleHandle],DSM_SMP_STREAM
- jne @@notstream
-
- IFDEF __16__
- xor eax,eax
- ENDIF
- ; Check if we would reach stream write position before the loop end:
- mov _ax,[_gsbx+dsmChannel.streamWritePos]
- cmp _ax,[position]
- jb @@notstream ; nope
-
- ; Check if we have any data in stream buffer:
- je @@nodata ; nothing to do - no data
-
- ; Calculate the number of sample bytes to write position:
- sub _ax,[position] ; _ax = number of sample bytes
- mov edx,eax ; edx:eax = number of sample bytes in
- shr edx,16 ; 16.16 fixed point format
- shl eax,16
- IFDEF __16__
- xor ecx,ecx
- mov cx,[posLow] ; substract position fractional part
- sub eax,ecx
- ELSE
- sub eax,[posLow]
- ENDIF
- sbb edx,0
-
- jmp @@loopset
-
-
- @@notstream:
- ; Check current loop type:
- mov _ax,[lpType]
- cmp _ax,loopNone
- je @@noloop
- cmp _ax,loopUnidir
- je @@unidir
-
- ; Bidirectional loop, check direction:
- cmp [direction],-1
- je @@bdback
-
- ; Bidirectional loop forwards - calculate number of sample bytes to
- ; loop end:
- IFDEF __16__
- xor eax,eax
- ENDIF
- mov _ax,[lpEnd] ; _ax = number of sample bytes
- sub _ax,[position] ; before loop end
- mov edx,eax ; edx:eax = number of sample bytes in
- shr edx,16 ; 16.16 fixed point format
- shl eax,16
- IFDEF __16__
- xor ecx,ecx
- mov cx,[posLow] ; substract position fractional part
- sub eax,ecx
- ELSE
- sub eax,[posLow]
- ENDIF
- sbb edx,0
-
- ; edx:eax now contains number of sample bytes to mix in 16.16
- ; fixed point format before loop end is reached
- jmp @@loopset
-
-
- @@bdback:
- ; Bidirectional loop backwards - calculate number of sample bytes to
- ; loop start:
- IFDEF __16__
- xor eax,eax
- ENDIF
- mov _ax,[position] ; _ax = number of sample bytes before
- sub _ax,[lpStart] ; loop end
- mov edx,eax ; edx:eax = number of sample bytes in
- shr edx,16 ; 16.16 fixed point format
- shl eax,16
- IFDEF __16__
- xor ecx,ecx
- mov cx,[posLow] ; add position fractional part
- add eax,ecx
- ELSE
- add eax,[posLow]
- ENDIF
- adc edx,0
-
- ; edx:eax now contains number of sample bytes to mix in 16.16
- ; fixed point format before loop end is reached
- jmp @@loopset
-
-
- @@unidir:
- ; Unidirectional loop - calculate number of sample bytes to loop end:
- IFDEF __16__
- xor eax,eax
- ENDIF
- mov _ax,[lpEnd] ; _ax = number of sample bytes
- sub _ax,[position] ; before loop end
- mov edx,eax ; edx:eax = number of sample bytes in
- shr edx,16 ; 16.16 fixed point format
- shl eax,16
- IFDEF __16__
- xor ecx,ecx
- mov cx,[posLow] ; substract position fractional part
- sub eax,ecx
- ELSE
- sub eax,[posLow]
- ENDIF
- sbb edx,0
-
- ; edx:eax now contains number of sample bytes to mix in 16.16
- ; fixed point format before loop end is reached
- jmp @@loopset
-
-
- @@noloop:
- ; No loop - calculate number of sample bytes to sample end:
- IFDEF __16__
- xor eax,eax
- ENDIF
- mov _ax,[_gsbx+dsmChannel.sampleLength] ; _ax = number of
- sub _ax,[position] ; sample bytes before sampleloop end
- mov edx,eax ; edx:eax = number of sample bytes in
- shr edx,16 ; 16.16 fixed point format
- shl eax,16
- IFDEF __16__
- xor ecx,ecx
- mov cx,[posLow] ; substract position fractional part
- sub eax,ecx
- ELSE
- sub eax,[posLow]
- ENDIF
- sbb edx,0
-
-
- @@loopset:
- ; edx:eax now contains number of sample bytes to mix in 16.16
- ; fixed point format before loop end is reached
-
- ; Check if maxMix (maximum number of sample bytes that can be mixed
- ; now) is below calculated number of bytes. If so, mix all that is
- ; left and exit: (done to prevent divide overflows later)
-
- mov ecx,[maxMix] ; ecx = maximum number of sample bytes
- shr ecx,16
- cmp ecx,edx ; check high word of whole part
- jb @@mixmax
-
- mov ecx,[maxMix]
- shl ecx,16
- cmp ecx,eax ; check low word of whole part
- jb @@mixmax
-
-
- ; Now calculate the number of destination elements the number of
- ; sample bytes in edx:eax corresponds to: (this still could overflow,
- ; but it only should happen with playing rates over 800kHz if tempo
- ; is above 31bpm or mixing buffers over 1/13th of a second in length)
-
- div [incr] ; eax = edx:eax / increment
- test edx,edx ; if modulus is not zero, one more
- jz @@nomod ; element must be mixed to actually
- inc eax ; reach loop end
-
- @@nomod:
- IFDEF __16__
- cmp eax,0FFFFh ; limit to 65535 elements (just to
- jb @@eaxok ; make sure there is no unwanted
- mov eax,0FFFFh ; truncation)
- @@eaxok:
- ENDIF
-
- cmp _ax,[mixLeft] ; do not mix more elements than there
- jbe @@mixlset ; is left to do for this mixing
- mov _ax,[mixLeft] ; process
- jmp @@mixlset
-
-
- @@mixmax:
- ; The number of sample bytes to sample/loop end is less than the
- ; maximum number of sample bytes that can be mixed during the whole
- ; mixing process - do all remaining destination elements:
- mov _ax,[mixLeft]
-
- @@mixlset:
- ; eax = number of destination elements to mix
- sub [mixLeft],_ax ; decrease number of elements left
-
- cmp [volume],0 ; is volume zero?
- je @@zerovol ; if so, just advance mixing position
-
- ; Call the actual low-level mixing routine:
- PUSHSEGREG gs
- push _bx
- push _bp
-
- IFDEF __16__
- ; In 16-bit modes store position before mixing so that it can be used
- ; for checking for bidirectional loop start. This is necessary as the
- ; playing position can wrap if the loop start is at the very start of
- ; the sample and there would be no way of knowing if this happened.
- ; In 32-bit modes wrapping is also possible, but it would only cause
- ; problems with loops longer than 2 gigabytes.
- mov _dx,[position]
- mov [prevPos],_dx
- ENDIF
-
- LOADPTR gs,_si,[sample] ; point _gssi to sample
- add _si,[position] ; point _gssi to current mixing pos.
- mov bl,[byte channel] ; bl = channel number
- mov bh,[byte volume] ; bh = volume
- mov _bp,[posLow] ; _bp = mixing position fract. part
- mov edx,[incr] ; edx = mixing position increment
- mov _cx,_ax ; _cx = number of elements to mix
- mov _di,[_int dest] ; _di points to mixing destination
-
- cmp [direction],-1 ; playing backwards?
- jne @@noback ; if yes, negate direction
- neg edx
-
- @@noback:
- ; Mix the sound: (we can't do call [mixRout] as it would confuse
- ; the wdisasm/gasm procedure we use to convert this to Linux)
- mov eax,[mixRout]
- call eax
- ; call [mixRout] ; mix the sound!
-
- mov [posLow],_bp ; store new position fractional part
- sub _si,[_int sample]
- mov [position],_si ; store new position whole part
- mov [_int dest],_di ; store new mixing destination pos.
-
- pop _bp
- pop _bx
- POPSEGREG gs
-
- jmp @@mixdone
-
-
- @@zerovol:
- ; Zero volume - just update mixing position: (eax = number of
- ; destination elements to mix)
-
- mov _cx,_ax ; _cx = number of dest. elements
- mov edx,[incr] ; edx = position increment
- cmp [direction],-1 ; playing backwards?
- jne @@zvfwd
- neg edx ; if yes, negate direction
- @@zvfwd:
- imul edx
-
- ; edx:eax is now the number of sample bytes "mixed" - add it to
- ; sample playing position: (could use some optimization and thinking)
- IFDEF __16__
- mov edx,eax
- sar eax,16 ; update position (number of sample
- add [posLow],ax ; bytes mixed always fits in 16 bits)
- adc [position],dx
- ELSE
- mov esi,[position]
- mov edi,esi ; edi:esi is current playing position
- shl esi,16 ; in 16.16 fixed point format
- sar edi,16
- mov si,[word posLow]
-
- add esi,eax ; update position in edi:esi
- adc edi,edx
-
- mov [word posLow],si ; set new position fractional part
-
- shr esi,16
- shl edi,16 ; set new position whole part
- or esi,edi
- mov [position],esi
- ENDIF
-
- cmp [channel],0 ; is this the first channel?
- jne @@mixdone ; if not, mixing is done
-
- ; First channel - clear mixing buffer for this area:
- ; (_cx still contains number of elements)
- PUSHSEGREG ds
- push _bx
- LOADPTR ds,_di,[dest]
- call Clear
- mov [_int dest],_di
- pop _bx
- POPSEGREG ds
-
-
-
- @@mixdone:
- ; Mixing is finished. Sample end or loop end might have been reached
- ; or we might simply have mixed all elements for this process. Check
- ; what is the case and proceed accordingly:
-
- cmp [lpType],loopNone ; is there no loop? if so, just check
- je @@checksmpend ; if sample end was reached
-
- cmp [direction],-1 ; going backwards? If so, check if
- je @@backwards ; loop start was reached
-
- ; Mixing forward and there is a loop - check if we reached loop end:
- mov _ax,[position] ; is position below loop end?
- cmp _ax,[lpEnd] ; if is, all mixing is done
- jae @@loopend
-
- ; We didn't, but if we were playing a stream we might have reached
- ; stream write position - just loop then to make sure:
- cmp [_esbx+dsmChannel.sampleHandle],DSM_SMP_STREAM
- jne @@alldone
- jmp @@loop
-
- @@loopend:
- ; Loop end was reached. Check if we should call the callback:
- cmp [loopCallback],0
- je @@noloopcb1
-
- ; Call it!
- ; Again, avoid GNU asm confusion:
- mov eax,[loopCallback]
- call eax LANG, [channel]
- ; call [_ptr loopCallback] LANG, [channel]
-
- @@noloopcb1:
- ; Check if ALE sample change is necessary:
- cmp [ALEChange],1
- je @@alechange
-
- ; ALE sample change not needed. Check if sound has been released and
- ; we should change to second loop:
- cmp [released],1
- je @@released
-
- ; None of the above. Check loop type:
- cmp [lpType],loopUnidir
- je @@unidirend
-
-
- ; Bidirectional loop end reached - start playing backwards and set
- ; position to lpEnd - (position - lpEnd) = 2*lpEnd - position
- mov [direction],-1
-
- IFDEF __16__
- mov ax,[lpEnd] ; edx = eax = lpEnd in 16.16 fixed
- shl eax,16 ; point format
- mov edx,eax
- mov si,[position] ; esi = position in 16.16 fixed point
- shl esi,16 ; format
- mov si,[posLow]
- sub eax,esi ; eax = lpEnd - (position - lpEnd)
- add eax,edx
-
- mov [posLow],ax ; store new position
- shr eax,16
- mov [position],ax
- ELSE
- mov esi,[lpEnd]
- mov edi,esi ; edi:esi = lpEnd in 16.16 fixed
- shl esi,16 ; point format
- shr edi,16
-
- add esi,esi ; edi:esi = 2*lpEnd
- adc edi,edi
-
- mov edx,eax ; edx:eax = position in 16.16 fixed
- shl eax,16 ; point format
- sar edx,16
- mov ax,[word posLow]
-
- sub esi,eax ; edi:esi = 2*lpEnd - position
- sbb edi,edx
-
- mov [word posLow],si
- shr esi,16 ; store new position
- shl edi,16
- or esi,edi
- mov [position],esi
- ENDIF
- jmp @@checkend
-
-
- @@unidirend:
- ; Unidirectional loop end reached - substract loop length from
- ; playing position:
- mov _ax,[lpEnd]
- sub _ax,[lpStart]
- sub [position],_ax
- jmp @@checkend
-
-
- @@backwards:
- ; Playing backwards - check if we reached bidirectional loop start:
- IFDEF __32__
- ; 32-bit mode - just check if playing position is below loop start
- ; position: (Use signed comparison to take care of possible wrapping,
- ; so that it won't cause any problems unless the loop is over 2
- ; gigabytes long)
- mov _ax,[position] ; if position is above or equal to
- cmp _ax,[lpStart] ; loop start, all mixing is done
- jge @@alldone
- ELSE
- ; 16-bit mode - the check above must be done unsigned, and therefore
- ; we also need to check if the playing position after mixing is above
- ; that of before. In that case the position has wrapped and we have
- ; reached loop start:
- mov _ax,[position]
- cmp _ax,[prevPos] ; has position wrapped?
- ja @@bdlpstart ; if yes, we are at loop start
-
- cmp _ax,[lpStart] ; if position is above or equal to
- jae @@alldone ; loop start, all mixing is done
-
- @@bdlpstart:
- ENDIF
- ; Bidirectional loop start has been reached. Check if we should call
- ; the callback:
- cmp [loopCallback],0
- je @@noloopcb2
-
- ; Call it!
- ; GNU asm fix
- mov eax,[loopCallback]
- call eax LANG, [channel]
- ; call [_ptr loopCallback] LANG, [channel]
-
- @@noloopcb2:
- ; Change direction and
- ; set new position to (lpStart-position) + lpStart
- mov [direction],1
- IFDEF __16__
- mov si,[lpStart] ; esi = lpStart in 16.16 fixed point
- shl esi,16 ; format
- shl eax,16 ; eax = position in 16.16 fixed point
- mov ax,[posLow] ; format
- mov edx,esi
- sub esi,eax ; esi = lpStart - position + lpStart
- add esi,edx
-
- mov [posLow],si ; store new position
- shr esi,16
- mov [position],si
- ELSE
- mov esi,[lpStart]
- mov edi,esi ; edi:esi = lpStart in 16.16 fixed
- shl esi,16 ; point format
- shr edi,16
-
- add esi,esi ; edi:esi = lpStart*2
- adc edi,edi ; (a - b + a = 2a - b)
-
- mov edx,eax ; edx:eax = position in 16.16 fixed
- shl eax,16 ; point format
- sar edx,16
- mov ax,[word posLow]
-
- sub esi,eax ; edi:esi = lpStart - position +
- sbb edi,edx ; lpStart = 2*lpStart - position
-
- mov [word posLow],si
- shr esi,16 ; store new position
- shl edi,16
- or esi,edi
- mov [position],esi
- ENDIF
- jmp @@checkend
-
-
- @@checksmpend:
- ; No loop - check if sample end has been reached:
- mov _ax,[position] ; position below
- cmp _ax,[_gsbx+dsmChannel.sampleLength] ; sample end? if not,
- jb @@alldone ; all mixing is done
-
- ; Sample end reached. Check if ALE sample changing is necessary:
- cmp [ALEChange],1
- je @@alechange
-
- ; ALE sample changing not necessary - sample has ended:
- mov [_gsbx+dsmChannel.status],dsmChanEnd
- jmp @@nodata
-
-
- @@checkend:
- ; Loop end/start succesfully handled. Check if there is more data
- ; to mix, and if not, exit
- cmp [mixLeft],0
- je @@alldone
- jmp @@loop ; loop sample
-
-
- @@alechange:
- ; Loop end or sample end has been reached and new sample has to be
- ; taken into use (ALE logic):
- PUSHSEGREG gs
- push _bx
- call dsmChangeSample LANG, [channel]
- pop _bx
- POPSEGREG gs
- test _ax,_ax
- jnz @@err
-
- ; If new sample is looping start playing from loop start, otherwise
- ; stop playing:
- cmp [_gsbx+dsmChannel.loopMode],sdLoopAmiga
- jne @@alenol
-
- ; Start playing from sample loop start:
- mov _ax,[_gsbx+dsmChannel.loop1Start]
- mov [position],_ax
- mov [posLow],0
- jmp @@newsample
-
- @@alenol:
- ; stop playing:
- mov [_gsbx+dsmChannel.status],dsmChanEnd
- jmp @@nodata
-
-
- @@released:
- ; Sound had been released, but loop had not been changed yet. Now when
- ; we have reached first loop end set values for second loop and
- ; continue playing:
-
- mov [_gsbx+dsmChannel.loopNum],2 ; playing second loop
- mov [released],0 ; sound releasing handled
- mov _ax,[_gsbx+dsmChannel.loop2Start]
- mov [lpStart],_ax
- mov _ax,[_gsbx+dsmChannel.loop2End]
- mov [lpEnd],_ax
- mov _ax,[_gsbx+dsmChannel.loop2Type]
- mov [lpType],_ax
-
- jmp @@loop
-
-
-
- @@nodata:
- ; No more data to be mixed - if this is the first channel clear
- ; the rest of the mixing buffer, otherwise we are done:
- cmp [channel],0
- jne @@alldone
-
- ; Clear the rest of the mixing buffer:
- PUSHSEGREG ds
- push _bx
- mov _cx,[mixLeft]
- LOADPTR ds,_di,[dest]
- call Clear
- pop _bx
- POPSEGREG ds
-
-
- @@alldone:
- ; All mixing done - save new mixing position and direction:
- mov _ax,[position]
- mov [_gsbx+dsmChannel.playPos],_ax
- mov _ax,[posLow]
- mov [_gsbx+dsmChannel.playPosLow],_ax
- mov _ax,[direction]
- mov [_gsbx+dsmChannel.direction],_ax
-
- @@ok:
- xor _ax,_ax
- jmp @@done
-
- @@err:
- ERROR ID_dsmMix
-
- @@done:
- ret
- ENDP
-
-
-
-
- IFDEF __16__
-
- ; mono mixing routine: (16-bit)
- MACRO _mono num
- mov bl,[gs:si] ; take byte from source
- add bp,cx ; increment sample position fraction
- mov ax,[ebx+ebx] ; take correct value from volume tbl
- adc si,dx ; increment sample position whole part
- add [di+2*num],ax ; add word into buffer
- ENDM
- MixLoop mono, _mono, 32, [fs:mixCount]
-
- ELSE
-
- ; mono mixing routine: (32-bit)
- MACRO _mono num
- mov bl,[esi] ; take byte from source
- add ebp,ecx ; increment sample position fraction
- mov eax,[4*ebx] ; take correct value from volume tbl
- adc esi,edx ; increment sample position whole part
- add [edi+4*num],eax ; add word into buffer
- ENDM
- MixLoop mono, _mono, 64, bp
-
- ENDIF
-
-
- IFDEF __16__
-
- ; mono mixing routine, first channel: (16-bit)
- MACRO _monom num
- mov bl,[gs:si] ; take byte from source
- add bp,cx ; increment sample position fraction
- mov ax,[ebx+ebx] ; take correct value from volume tbl
- adc si,dx ; increment sample position whole part
- mov [di+2*num],ax ; write word into buffer
- ENDM
- MixLoop monom, _monom, 32, [fs:mixCount]
-
- ELSE
-
- ; mono mixing routine, first channel: (32-bit)
- MACRO _monom num
- mov bl,[esi] ; take byte from source
- add ebp,ecx ; increment sample position fraction
- mov eax,[4*ebx] ; take correct value from volume tbl
- adc esi,edx ; increment sample position whole part
- mov [edi+4*num],eax ; write word into buffer
- ENDM
- MixLoop monom, _monom, 64, bp
-
- ENDIF
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: dsmMix8bitMonoMono
- ;*
- ;* Description: Mixing routine for 8-bit mono samples to mono output
- ;*
- ;* Input: gs sample data segment (16-bit only)
- ;* _si sample mixing position whole part, from the
- ;* beginning of the sample segment
- ;* _bp sample position fractional part, only lower
- ;* 16 bits used
- ;* edx sample mixing position increment for each
- ;* destination byte, 16.16 fixed point format
- ;* _di pointer to mixing buffer (assumed to be in
- ;* the volume table segment)
- ;* _cx number of destination elements to mix
- ;* bh volume to be used
- ;* bl current channel number
- ;* [ds:panning] channel panning position
- ;*
- ;* Returns: _si._bp new mixing position (same format as input)
- ;* _di new destination position
- ;*
- ;* Destroys: eax, ebx, ecx, edx, esi, edi
- ;*
- ;\***************************************************************************/
-
- PROC dsmMix8bitMonoMono _funct
-
- test _cx,_cx ; don't mix zero bytes
- jz @@done
-
- test bl,bl ; first channel?
- jne @@notfirst
- mov [mixLoop],offset monom ; first channel - move to buffer
- jmp @@mlok
-
- @@notfirst:
- mov [mixLoop],offset mono ; not the first channel - add to buf.
-
- @@mlok:
- call MixMono
-
- @@done:
- ret
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: void MixMono(void)
- ;*
- ;* Description: Common code for all mono mixing routines.
- ;*
- ;\***************************************************************************/
-
- PROC MixMono _funct
-
- add bh,VOLADD ; convert volume rounding up
- shr bh,VOLSHIFT
- mov al,bh
- xor ebx,ebx ; bh contains volume and bl sample
- mov bh,al
-
- mov eax,[dsmVolumeTable] ; add volume table offset / 4 to
- shr eax,2 ; ebx in 32-bit modes
- add ebx,eax
-
- mov eax,ecx ; eax = number of elements to mix
- and eax,15 ; in the first loop
-
- shl eax,2
- neg eax ; eax = jump table offset (64 - 4*eax)
- add eax,64
-
- sub edi,eax ; undo edi incrementing in loop
- add eax,[mixLoop]
- mov eax,[eax]
-
- shr ecx,4 ; ecx = number of loops to mix
- inc ecx
-
- shl ebp,16 ; set position whole part to ebp
- ; upper word
- mov bp,cx ; set loop counter to bp
-
- mov ecx,edx ; ecx = mixing position increment
- shl ecx,16 ; fractional part
- sar edx,16 ; edx = increment whole part
-
- call eax ; call the mixing routine
-
- shr ebp,16 ; restore position fractional part
- ; to ebp lower 16 bits
- @@done:
- ret
- ENDP
-
-
-
-
- ; left mixing routine: (32-bit)
- MACRO _left num
- mov bl,[esi] ; take byte from source
- add ebp,ecx ; increment sample position fraction
- mov eax,[4*ebx] ; take correct value from volume tbl
- adc esi,edx ; increment sample position whole part
- add [edi+8*num],eax ; add word into buffer
- ENDM
- MixLoop left, _left, 128, bp
-
-
- ; right mixing routine: (32-bit)
- MACRO _right num
- mov bl,[esi] ; take byte from source
- add ebp,ecx ; increment sample position fraction
- mov eax,[4*ebx] ; take correct value from volume tbl
- adc esi,edx ; increment sample position whole part
- add [edi+8*num+4],eax ; add word into buffer
- ENDM
- MixLoop right, _right, 128, bp
-
-
- ; middle mixing routine: (32-bit)
- MACRO _middle num
- mov bl,[esi] ; take byte from source
- add ebp,ecx ; increment sample position fraction
- mov eax,[4*ebx] ; take correct value from volume tbl
- adc esi,edx ; increment sample position whole part
- add [edi+8*num],eax ; add word to left channel
- add [edi+8*num+4],eax ; add word to right channel
- ENDM
- MixLoop middle, _middle, 128, bp
-
-
- ; right mixing routine: (32-bit)
- MACRO _surround num
- mov bl,[esi] ; take byte from source
- add ebp,ecx ; increment sample position fraction
- mov eax,[4*ebx] ; take correct value from volume tbl
- adc esi,edx ; increment sample position whole part
- add [edi+8*num],eax ; add word to left channel
- sub [edi+8*num+4],eax ; add word to right channel
- ENDM
- MixLoop surround, _surround, 128, bp
-
-
- ; smooth panning mixing routine: (32-bit) (S-L-O-W)
- MACRO _smooth num
- mov bl,[esi] ; take byte from source
- add ebp,[fracIncr] ; increment sample position fraction
- mov cl,bl
- mov eax,[4*ebx] ; take correct value from volume tbl
- adc esi,edx ; increment sample position whole part
- add [edi+8*num],eax ; add word to left channel
- mov eax,[4*ecx]
- add [edi+8*num+4],eax ; add word to right channel
- ENDM
- MixLoop smooth, _smooth, 128, bp
-
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: void dsmMix8bitMonoStereo(void)
- ;*
- ;* Description: Mixing routine for 8-bit mono samples to stereomono output
- ;* See dsmMix8bitMonoMono() for input/output documentation.
- ;*
- ;\***************************************************************************/
-
- PROC dsmMix8bitMonoStereo _funct
-
- @@ook:
- test _cx,_cx ; don't mix zero bytes
- jz @@done
-
- test bl,bl ; first channel?
- jne @@notfirst
-
- ; This is the first channel - first clear the destination area
- push _di _cx
- shl ecx,1
- xor eax,eax
- rep stosd
- pop _cx _di
-
- @@notfirst:
- ; Check the channel panning position to determine which mixing
- ; routine to use: (plus the smooth panning routine requires some
- ; extra work here)
- mov _ax,[panning]
- cmp _ax,panLeft
- je @@left
- cmp _ax,panRight
- je @@right
- cmp _ax,panMiddle
- je @@middle
- cmp _ax,panSurround
- je @@surround
-
- ; Smooth panning
- mov [mixLoop],offset smooth ; use smooth panning routine
-
- call MixStereo
- jmp @@done
-
-
- @@left:
- mov [mixLoop],offset left
- jmp @@mlok
-
- @@right:
- mov [mixLoop],offset right
- jmp @@mlok
-
- @@middle:
- mov [mixLoop],offset middle
- jmp @@mlok
-
- @@surround:
- mov [mixLoop],offset surround
- jmp @@mlok
-
-
- @@mlok:
- ; Build correct value to ebx:
- add bh,VOLADD ; convert volume rounding up
- shr bh,VOLSHIFT
- and ebx,0000FF00h ; bh contains volume and bl sample
-
- mov eax,[dsmVolumeTable] ; add volume table offset / 4 to
- shr eax,2 ; ebx in 32-bit modes
- add ebx,eax
-
- mov eax,ecx ; eax = number of elements to mix
- and eax,15 ; in the first loop
-
- shl eax,2
- neg eax ; eax = jump table offset (64 - 4*eax)
- add eax,64
-
- sub edi,eax ; undo edi incrementing in loop
- sub edi,eax
- add eax,[mixLoop]
- mov eax,[eax]
-
- shr ecx,4 ; ecx = number of loops to mix
- inc ecx
-
- shl ebp,16 ; set position whole part to ebp
- ; upper word
- mov bp,cx ; set loop counter to bp
-
- mov ecx,edx ; ecx = mixing position increment
- shl ecx,16 ; fractional part
- sar edx,16 ; edx = increment whole part
-
- call eax ; call the mixing routine
-
- shr ebp,16 ; restore position fractional part
- ; to ebp lower 16 bits
- @@done:
- ret
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: void MixStereo(void)
- ;*
- ;* Description: Common code for all stereo mixing routines (smooth panning
- ;* ones)
- ;*
- ;\***************************************************************************/
-
- PROC MixStereo _funct
-
- ; Calculate the volumes for left and right channels
-
- mov bl,[byte panning]
- mov al,bh
- test bl,bl
- jns @@spright
-
- ; Panning is < 0 (left) - set left channel volume to full value and
- ; right to volume * (64+panning) / 64:
- mov [leftVolume],al
- add bl,64
- mul bl
- shr _ax,6
- mov [rightVolume],al
- jmp @@spvol
-
- @@spright:
- ; Panning is > 0 (right) - set right channel volume to full value and
- ; left to volume * (64-panning) / 64:
- mov [rightVolume],al
- neg bl
- add bl,64
- mul bl
- shr _ax,6
- mov [leftVolume],al
-
- @@spvol:
- ; Write mixing position fractional part increment to [fracIncr]:
- mov eax,edx
- shl eax,16
- mov [fracIncr],eax
-
- mov eax,ecx ; eax = number of elements to mix
- and eax,15 ; in the first loop
-
- shl eax,2
- neg eax ; eax = jump table offset (64 - 4*eax)
- add eax,64
-
- sub edi,eax ; undo edi incrementing in loop
- sub edi,eax
- add eax,[mixLoop]
- mov eax,[eax]
-
- shr ecx,4 ; ecx = number of loops to mix
- inc ecx
-
- shl ebp,16 ; set position whole part to ebp
- ; upper word
- mov bp,cx ; set loop counter to bp
-
- sar edx,16 ; edx = increment whole part
-
- push eax
-
- ; Set ebx to left channel volume * 256
- mov bh,[leftVolume]
- add bh,VOLADD ; convert volume rounding up
- shr bh,VOLSHIFT
- and ebx,0000FF00h ; bh contains volume and bl sample
-
- mov eax,[dsmVolumeTable]
- shr eax,2
- add ebx,eax
-
- ; Set ecx to right channel volume * 256
- mov ch,[rightVolume]
- add ch,VOLADD ; convert volume rounding up
- shr ch,VOLSHIFT
- and ecx,0000FF00h ; ch contains volume and cl sample
-
- add ecx,eax
-
- pop eax
-
- call eax ; call the mixing routine
-
- shr ebp,16 ; restore position fractional part
- ; to ebp lower 16 bits
-
- ret
- ENDP
-
-
-
- ; 8-bit stereo => mono mixing routine: (32-bit) (S-L-O-W)
- MACRO _m8stmo num
- mov bl,[2*esi] ; take byte from source
- add ebp,ecx ; increment sample position fraction
- mov eax,[4*ebx] ; take correct value from volume tbl
- mov bl,[2*esi+1] ; take right byte
- adc esi,edx ; increment sample position whole part
- add eax,[4*ebx] ; add its value
- add [edi+4*num],eax ; add word into buffer
- ENDM
- MixLoop m8stmo, _m8stmo, 64, bp
-
- PROC dsmMix8bitStereoMono _funct
-
- test _cx,_cx ; don't mix zero bytes
- jz @@done
-
- test bl,bl ; first channel?
- jne @@notfirst
-
- ; This is the first channel - first clear the destination area
- push _di _cx
- xor eax,eax
- rep stosd
- pop _cx _di
-
- @@notfirst:
- ; Divide volume by two - we'll add the channels together:
- inc bh
- shr bh,1
-
- mov [mixLoop],offset m8stmo ; not the first channel - add to buf.
-
- call MixMono
-
- @@done:
- ret
- ENDP
-
-
-
-
- ; 8-bit stereo => stereo mixing routine: (32-bit) (S-L-O-W)
- MACRO _m8stst num
- mov bl,[2*esi] ; take left byte from source
- add ebp,[fracIncr] ; increment sample position fraction
- mov cl,[2*esi+1] ; take right byte from source
- mov eax,[4*ebx] ; take correct value from volume tbl
- adc esi,edx ; increment sample position whole part
- add [edi+8*num],eax ; add word to left channel
- mov eax,[4*ecx]
- add [edi+8*num+4],eax ; add word to right channel
- ENDM
- MixLoop m8stst, _m8stst, 128, bp
-
- PROC dsmMix8bitStereoStereo _funct
-
- @@ook:
- test _cx,_cx ; don't mix zero bytes
- jz @@done
-
- test bl,bl ; first channel?
- jne @@notfirst
-
- ; This is the first channel - first clear the destination area
- push _di _cx
- shl ecx,1
- xor eax,eax
- rep stosd
- pop _cx _di
-
- @@notfirst:
- ; Mix 8-bit stereo samples to stereo destination:
- mov [mixLoop],offset m8stst
-
- call MixStereo
-
- @@done:
- ret
- ENDP
-
-
-
- ; 16-bit mono => mono mixing routine: (32-bit) (S-L-O-W)
- MACRO _m16momo num
- mov bl,[2*esi]
- add ebp,ecx ; increment sample position fraction
- mov eax,[4*ebx]
- mov bl,[2*esi+1]
- adc esi,edx ; increment sample position whole part
- sar eax,8
- xor bl,80h
- add eax,[4*ebx]
- add [edi+4*num],eax ; add word to left channel
- ENDM
- MixLoop m16momo, _m16momo, 64, bp
-
- PROC dsmMix16bitMonoMono _funct
-
- test _cx,_cx ; don't mix zero bytes
- jz @@done
-
- test bl,bl ; first channel?
- jne @@notfirst
-
- ; This is the first channel - first clear the destination area
- push _di _cx
- xor eax,eax
- rep stosd
- pop _cx _di
-
- @@notfirst:
- mov [mixLoop],offset m16momo ; not the first channel - add to buf.
-
- call MixMono
-
- @@done:
- ret
- ENDP
-
-
-
- ; 16-bit mono => stereo mixing routine: (32-bit) (S-L-O-W)
- MACRO _m16most num
- mov bl,[2*esi]
- add ebp,[fracIncr] ; increment sample position fraction
- mov eax,[4*ebx]
- mov cl,bl
- mov bl,[2*esi+1]
- adc esi,edx ; increment sample position whole part
- sar eax,8
- xor bl,80h
- add eax,[4*ebx]
- add [edi+8*num],eax ; add word to left channel
- mov eax,[4*ecx]
- mov cl,bl
- sar eax,8
- add eax,[4*ecx]
- add [edi+8*num+4],eax
- ENDM
- MixLoop m16most, _m16most, 128, bp
-
- PROC dsmMix16bitMonoStereo _funct
-
- test _cx,_cx ; don't mix zero bytes
- jz @@done
-
- test bl,bl ; first channel?
- jne @@notfirst
-
- ; This is the first channel - first clear the destination area
- push _di _cx
- shl ecx,1
- xor eax,eax
- rep stosd
- pop _cx _di
-
- @@notfirst:
- ; Mix 8-bit stereo samples to stereo destination:
- mov [mixLoop],offset m16most
-
- call MixStereo
-
- @@done:
- ret
- ENDP
-
-
-
- ; 16-bit stereo => mono mixing routine: (32-bit) (S-L-O-W)
- MACRO _m16stmo num
- mov bl,[4*esi]
- mov eax,[4*ebx]
- mov bl,[4*esi+2]
- add eax,[4*ebx]
- mov bl,[4*esi+1]
- sar eax,8
- xor bl,80h
- add eax,[4*ebx]
- mov bl,[4*esi+3]
- xor bl,80h
- add ebp,ecx ; increment sample position fraction
- adc esi,edx ; increment sample position whole part
- add eax,[4*ebx]
- add [edi+4*num],eax ; add word to left channel
- ENDM
- MixLoop m16stmo, _m16stmo, 64, bp
-
- PROC dsmMix16bitStereoMono _funct
-
- test _cx,_cx ; don't mix zero bytes
- jz @@done
-
- test bl,bl ; first channel?
- jne @@notfirst
-
- ; This is the first channel - first clear the destination area
- push _di _cx
- xor eax,eax
- rep stosd
- pop _cx _di
-
- @@notfirst:
- ; Divide volume by two - we'll add the channels together:
- inc bh
- shr bh,1
-
- mov [mixLoop],offset m16stmo ; not the first channel - add to buf.
-
- call MixMono
-
- @@done:
- ret
- ENDP
-
-
-
- ; 16-bit stereo => stereo mixing routine: (32-bit) (S-L-O-W)
- MACRO _m16stst num
- mov bl,[4*esi]
- mov eax,[4*ebx]
- mov bl,[4*esi+1]
- sar eax,8
- xor bl,80h
- add eax,[4*ebx]
- add [edi+8*num],eax ; add word to left channel
- mov cl,[4*esi+2]
- mov eax,[4*ecx]
- mov cl,[4*esi+3]
- sar eax,8
- xor cl,80h
- add ebp,[fracIncr] ; increment sample position fraction
- adc esi,edx ; increment sample position whole part
- add eax,[4*ecx]
- add [edi+8*num+4],eax
- ENDM
- MixLoop m16stst, _m16stst, 128, bp
-
- PROC dsmMix16bitStereoStereo _funct
-
- test _cx,_cx ; don't mix zero bytes
- jz @@done
-
- test bl,bl ; first channel?
- jne @@notfirst
-
- ; This is the first channel - first clear the destination area
- push _di _cx
- shl ecx,1
- xor eax,eax
- rep stosd
- pop _cx _di
-
- @@notfirst:
- ; Mix 8-bit stereo samples to stereo destination:
- mov [mixLoop],offset m16stst
-
- call MixStereo
-
- @@done:
- ret
- ENDP
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: int dsmClearBuffer(unsigned numElems)
- ;*
- ;* Description: Clears the mixing buffer. Used only by dsmMixData().
- ;*
- ;* Input: unsigned numElems number of elements to clear
- ;*
- ;* Returns: MIDAS error code.
- ;*
- ;\***************************************************************************/
-
- PROC dsmClearBuffer _funct numElems : _int
- USES _si,_di,_bx
-
- PUSHSEGREG ds
-
- LOADPTR ds,_di,[dsmMixBuffer] ; point es:di to mixing buffer
- mov _cx,[numElems] ; number of elements
-
- call Clear
-
- POPSEGREG ds
-
- xor _ax,_ax
-
- ret
- ENDP
-
-
-
-
- ;/***************************************************************************\
- ;*
- ;* Function: Clear
- ;*
- ;* Description: Clears part of the mixing buffer
- ;*
- ;* Input: _di Points to mixing buffer position
- ;* _cx Number of elements to clear
- ;*
- ;* Returns: _di New mixing buffer position
- ;*
- ;* Destroys: eax, _bx, _cx, _di
- ;*
- ;\***************************************************************************/
-
- PROC Clear NEAR
-
- ; FIXME - doesn't work with new fast stereo mixing
-
- PUSHSEGREG es
-
- test _cx,_cx
- jz @@done
-
- mov ax,ds
- mov es,ax
-
- xor eax,eax
- cld
-
- cmp [dsmMode],dsmMixStereo ; stereo mixing?
- jne @@mono
-
- shl _cx,1 ; twice the number of bytes
-
- @@mono:
- IFDEF __16__
- test di,2 ; aligned to a dword boundary?
- jz @@dword
- mov [es:di],ax ; nope, write one word
- add di,2
- dec cx
- jz @@done
- @@dword:
- mov bx,cx
- shr cx,1
- rep stosd ; fill all dwords
- test bx,1 ; still one word to fill?
- jz @@done
- mov [es:di],ax
- add di,2
- ELSE
- rep stosd
- ENDIF
- @@done:
- POPSEGREG es
-
- ret
- ENDP
-
-
-
- ;* $Log: dsmmix.asm,v $
- ;* Revision 1.9 1997/01/16 18:41:59 pekangas
- ;* Changed copyright messages to Housemarque
- ;*
- ;* Revision 1.8 1997/01/16 18:19:10 pekangas
- ;* Added support for setting the stream write position.
- ;* Stream data is no longer played past the write position
- ;*
- ;* Revision 1.7 1996/08/02 17:50:24 pekangas
- ;* Changed calls to pointer to go through eax to prevent GNU asm confusion
- ;*
- ;* Revision 1.6 1996/07/13 17:28:10 pekangas
- ;* Fixed to preserve ebx always
- ;*
- ;* Revision 1.5 1996/06/26 19:15:24 pekangas
- ;* Added sample loop callbacks
- ;*
- ;* Revision 1.4 1996/05/30 21:25:48 pekangas
- ;* Fixed a small bug in 16-bit stereo mixing routines
- ;*
- ;* Revision 1.3 1996/05/28 20:30:52 pekangas
- ;* Added mixing routines for 8-bit stereo and 16-bit samples
- ;*
- ;* Revision 1.2 1996/05/23 20:59:08 pekangas
- ;* Removed some DD 0FFFFFFFFh - lines to keep wdisasm from getting confused
- ;*
- ;* Revision 1.1 1996/05/22 20:49:33 pekangas
- ;* Initial revision
- ;*
-
-
- END